/**
 *  TextMash - simple IDE for Clojure
 *  
 *  Copyright (C) 2010 Aleksander Naszko
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *  
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package pl.olek.textmash;

import java.awt.Dimension;
import java.awt.Point;
import java.awt.Toolkit;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.Thread.UncaughtExceptionHandler;
import java.util.ArrayList;
import java.util.List;

import pl.olek.textmash.matching.Dictionary;
import pl.olek.textmash.menu.WorkspaceMenu;
import pl.olek.textmash.workspace.DialogBox;
import pl.olek.textmash.workspace.Settings;
import pl.olek.textmash.workspace.Workspace;

/**
 * 
 * @author anaszko
 *
 */
public class TextMash {

	static int locationRnd;

	static boolean closeAll;

	static ArrayList<String> recentFiles = new ArrayList<String>();

	static ArrayList<String> recentFolders = new ArrayList<String>();

	static ArrayList<Workspace> workspaces = new ArrayList<Workspace>();

	// static String fileToOpen = "";

	public synchronized static List<Workspace> getWorkspaces() {
		return workspaces;
	}

	public synchronized static List<Workspace> getWorkspaceClone() {
		return new ArrayList<Workspace>(getWorkspaces());
	}

	public synchronized static void actionClearRecentFolders() {
		recentFolders.clear();
		updateRecent();
	}
	
	public synchronized static boolean checkIfOpened(String dataSource){
		for(Workspace ws : workspaces) {
			if (!ws.isUnnamed() && ws.getDataSource().equals(dataSource)) {
				ws.toFront();
				return false;
			}
		}
		return true;
	}

	public synchronized static void actionOpenFile(String dataSource) {
		if (checkIfOpened(dataSource)) {
		if (workspaces.isEmpty()) {
			spawnWorkspace(dataSource);
		} else {
			workspaces.get(0).actionOpenFile(dataSource);
		}
		}
	}

	public synchronized static void actionClearRecentFiles() {
		recentFiles.clear();
		updateRecent();
	}

	public synchronized static ArrayList<String> getRecentFolders() {
		return recentFolders;
	}

	public synchronized static ArrayList<String> getRecentFiles() {
		return recentFiles;
	}

	public synchronized static void actionBringToFront(Workspace ws) {
		for (Workspace w : getWorkspaceClone()) {
			if (w != ws) {
				w.toFront();
			}
		}
		ws.toFront();
	}

	public synchronized static void save() {
		try {
			System.out.println("Storing state");
			ObjectOutputStream out = new ObjectOutputStream(
					new FileOutputStream(".textmash"));
			Settings.save(out);
			Dictionary.save(out);
			out.writeObject(recentFiles);
			out.writeObject(recentFolders);
			out.writeInt(locationRnd);
			out.close();
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	@SuppressWarnings("unchecked")
	public synchronized static void load() {
		try {
			
			File state = new File(".textmash");
			if (state.exists()) {
				ObjectInputStream in = new ObjectInputStream(
						new FileInputStream(state));
				Settings.load(in);
				Dictionary.load(in);
				recentFiles = (ArrayList<String>) in.readObject();
				recentFolders = (ArrayList<String>) in.readObject();
				locationRnd = in.readInt();
				in.close();
			}
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	public synchronized static Dimension getDefaultDimension() {
		return new Dimension(600, 500);
	}

	public synchronized static Point getDefaultLocation() {
		Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
		double where = ((locationRnd++ % 5) + 1) / 25.0;
		return new Point((int) (dim.width * where), (int) (dim.height * where));
	}

	public synchronized static void updateRecent(String dataSource) {
		if (dataSource.length() != 0) {
			File source = new File(dataSource);
			String file = source.getAbsolutePath();
			recentFiles.remove(file);
			recentFiles.add(file);
			String folder = source.getParent();
			recentFolders.remove(folder);
			recentFolders.add(folder);
			updateRecent();
		}
	}

	public synchronized static void actionCloseAll(Workspace ws) {
		for (Workspace w : getWorkspaceClone()) {
			if (w != ws) {
				w.actionClose();
			}
		}
		ws.actionClose();
	}

	public synchronized static void actionCloseOthers(Workspace ws) {
		for (Workspace w : getWorkspaceClone()) {
			if (w == ws) {
				continue;
			}
			w.actionClose();
		}
	}

	public synchronized static void updateOpened(boolean modify) {
		for (Workspace w : workspaces) {
			((WorkspaceMenu) w.getJMenuBar()).synchronizedWorkspaces(modify);
		}
	}

	public synchronized static void updateRecent() {
		for (Workspace w : workspaces) {
			((WorkspaceMenu) w.getJMenuBar()).synchronizeRecentFiles(w);
			((WorkspaceMenu) w.getJMenuBar()).synchronizeRecentFolders(w);
		}
	}

	public synchronized static void spawnWorkspace(String dataSource) {

		Workspace ws = new Workspace(dataSource);
		workspaces.add(ws);

		ws.setVisible(true);
		// if (ws.getDataSource().length() > 0) {
		// Support.getInstance().decorateWindow(ws, new File(dataSource));
		// }
		updateOpened(true);
	}

	public synchronized static void disposeWorkspace(Workspace ws) {
		workspaces.remove(ws);
		updateOpened(true);
	}

	public synchronized static void terminate() {
		TextMash.save();
		System.exit(0);
	}

	public static void main(String[] args) {
		
		Thread.setDefaultUncaughtExceptionHandler(new UncaughtExceptionHandler() {
			
			@Override
			public void uncaughtException(Thread t, Throwable e) {
				DialogBox.showErrorBox(null, "Oops! An unexpected error has occured...", e);
				
			}
		});

		String os = System.getProperty("os.name").toLowerCase();
		if (os.contains("mac")) {
			Support.setInstance(new MacOSXSupport());
		} else if (os.contains("win")) {
			Support.setInstance(new WindowsSupport());
		} else /* linux or unix */{
			Support.setInstance(new UnixSupport());
		}

		TextMash.load();

		TextMash.spawnWorkspace("");
	}

	public static void actionSaveAll() {
		for (Workspace w : getWorkspaceClone()) {
			w.actionSave();
		}
	}

}
